Asssumes you have aready run: - config - workflow_deepseaNiN_Start

You now have the objects needed to explore the dataset and find the best way to apply biogeographic splits. This is a pre-step before running the workflow again on the split dataset to explore possible LKMs.

Finding Regional (biogeographic) Splits

This requires exploring the dataset to theorise the best ways to split the data with: - environmental biplots/colourings

then applying the splits.

Libraries

library(plotly)
library(readxl)

Exploring biplots

make full dataset to explore

should include all env Vars and otus to explore, and make species richness variable

#add species data and sp richness variable
env_sub_meta1<-cbind(env,otu_6)
env_sub_meta1$spRich<-rowSums(otu_6[,-c(1:which(colnames(otu_6)=="Zoanthidae"))]!=0)

#rename X
env_sub_meta1$X <- env$X.y
env_sub_meta1 <-env_sub_meta1 %>% select (-c(X.y))

#add samplID
env_sub_meta1$SampID<-envSel$SampID

Add provisional biotope data to env file

Note that biotopes were last assigned in march 2022 and therefore there are some addional samples that have not yet got a biotope assigned. These should just be NAs

biotopeInfo<-read_xlsx(file.path(dataPath, "inputs/MAREANO_provisional_biotope_classification_0322.xlsx"), sheet=1) %>%
  select(-c(x_coordinate_UTM33N, y_coordinate_UTM33N))

env_sub_meta<-left_join(env_sub_meta1,biotopeInfo)

a colour palette for discrete plots (see later in script)

cbPalette <- c("#999999", "#E69F00", "#56B4E9", "#009E73", "#F0E442", "#0072B2", "#D55E00", "#CC79A7")

Find min max of vars for scales

summary(env_sub_meta)
 Tmean_Robinson      salt_max     Smax_Robinson   swDensRob_avs  BO22_icecoverltmax_ss
 Min.   :-1.067   Min.   :34.81   Min.   :34.43   Min.   :1027   Min.   :0.00000      
 1st Qu.: 4.544   1st Qu.:34.98   1st Qu.:35.01   1st Qu.:1028   1st Qu.:0.00000      
 Median : 6.563   Median :35.13   Median :35.13   Median :1029   Median :0.00000      
 Mean   : 5.880   Mean   :35.11   Mean   :35.12   Mean   :1029   Mean   :0.02214      
 3rd Qu.: 7.303   3rd Qu.:35.19   3rd Qu.:35.31   3rd Qu.:1029   3rd Qu.:0.00000      
 Max.   : 8.447   Max.   :35.82   Max.   :35.42   Max.   :1031   Max.   :0.92838      
 BO22_icecovermean_ss BO22_dissoxmean_bdmean BO22_ppltmin_ss          X.y                Y          
 Min.   :0.000000     Min.   :282.5          Min.   :0.000e+00   Min.   :-107939   Min.   :6944134  
 1st Qu.:0.000000     1st Qu.:286.3          1st Qu.:0.000e+00   1st Qu.: 161061   1st Qu.:7310134  
 Median :0.000000     Median :293.3          Median :1.465e-05   Median : 472061   Median :7742034  
 Mean   :0.007224     Mean   :299.1          Mean   :1.167e-04   Mean   : 503105   Mean   :7704256  
 3rd Qu.:0.000000     3rd Qu.:306.4          3rd Qu.:6.533e-05   3rd Qu.: 795711   3rd Qu.:8036584  
 Max.   :0.409033     Max.   :372.2          Max.   :1.067e-03   Max.   :1162261   Max.   :8949734  
    spd_std        CSpdsd_Robinson          mud            gravel     BO22_silicateltmax_bdmean
 Min.   :0.02103   Min.   :1.085e-05   Min.   : 0.00   Min.   : 0.0   Min.   :4.585            
 1st Qu.:0.05728   1st Qu.:3.842e-03   1st Qu.: 7.00   1st Qu.: 1.5   1st Qu.:5.895            
 Median :0.06776   Median :7.374e-03   Median :24.00   Median :18.0   Median :6.244            
 Mean   :0.07592   Mean   :9.038e-03   Mean   :26.99   Mean   :21.3   Mean   :6.292            
 3rd Qu.:0.08946   3rd Qu.:1.272e-02   3rd Qu.:35.00   3rd Qu.:35.0   3rd Qu.:6.529            
 Max.   :0.18145   Max.   :5.305e-02   Max.   :96.00   Max.   :65.0   Max.   :9.201            
     bathy             gnmds1            gnmds2               X          
 Min.   :-701.79   Min.   :-2.2304   Min.   :-1.80909   Min.   :-107939  
 1st Qu.:-353.88   1st Qu.:-0.4374   1st Qu.:-0.26894   1st Qu.: 161061  
 Median :-269.97   Median :-0.2373   Median :-0.06045   Median : 472061  
 Mean   :-293.06   Mean   : 0.0000   Mean   : 0.00000   Mean   : 503105  
 3rd Qu.:-199.75   3rd Qu.: 0.3848   3rd Qu.: 0.27439   3rd Qu.: 795711  
 Max.   : -38.61   Max.   : 1.8972   Max.   : 1.94516   Max.   :1162261  

Plots with CONTINUOUS colour scales (variables)

Bathy v Temp w gnmds ax 1
tb_ax1<- ggplot(data = env_sub_meta,
                      aes(x = Tmean_Robinson,
                          y = bathy)) +
  theme_classic() +
  geom_point(aes(colour = gnmds1),
             size = 1) +
  scale_colour_gradientn(limits = c(-2.3, 1.9),
                        colors=c('red','yellow','green'))+
  ggtitle("Temp (mean Robinson) vs Bathy - coloured by gnmds r6 ax1")

tb_ax1

Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1bathy_v_temp_nmds1.png"),
       device = "png",
       dpi=300 )
Saving 7 x 7 in image
Bathy v Temp w salinity
tb_ax1<- ggplot(data = env_sub_meta,
                      aes(x = Tmean_Robinson,
                          y = bathy)) +
  theme_classic() +
  geom_point(aes(colour = Smax_Robinson),
             size = 1) +
  scale_colour_gradientn(limits = c(34.43, 35.43),
                        colors=c('green','yellow','blue'))+
  ggtitle("Temp (mean Robinson) vs Bathy - coloured by salinity")

tb_ax1
Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1bathy_v_temp_salinityMax.png"),
       device = "png",
       dpi=300 )
Bathy v Temp w longitude
tb_ax1<- ggplot(data = env_sub_meta,
                      aes(x = Tmean_Robinson,
                          y = bathy)) +
  theme_classic() +
  geom_point(aes(colour = X.y),
             size = 1) +
  scale_colour_gradientn(limits = c(-107939, 1162261),
                        colors=c('red','yellow','blue'))+
  ggtitle("Temp (mean Robinson) vs Bathy - coloured by longitude")

tb_ax1
Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1bathy_v_temp_longitude.png"),
       device = "png",
       dpi=300 )
Bathy v Temp w latitude
tb_ax1<- ggplot(data = env_sub_meta,
                      aes(x = Tmean_Robinson,
                          y = bathy)) +
  theme_classic() +
  geom_point(aes(colour = Y),
             size = 1) +
  scale_colour_gradientn(limits = c(6944134, 8949734),
                        colors=c('red','yellow','blue'))+
  ggtitle("Temp (mean Robinson) vs Bathy - coloured by latitude")

tb_ax1
Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1bathy_v_temp_latitude.png"),
       device = "png",
       dpi=300 )
Bathy v Temp w iceCovLTMax
tb_ax1<- ggplot(data = env_sub_meta,
                      aes(x = Tmean_Robinson,
                          y = bathy)) +
  theme_classic() +
  geom_point(aes(colour = BO22_icecoverltmax_ss),
             size = 1) +
  scale_colour_gradientn(limits = c(0,0.93),
                        colors=c('grey','turquoise','blue'))+
  ggtitle("Temp (mean Robinson) vs Bathy - coloured by ice cover LT max")

tb_ax1
Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1bathy_v_temp_iceCovLTmax.png"),
       device = "png",
       dpi=300 )
Bathy v Salinity coloured by temp
tb_ax1<- ggplot(data = env_sub_meta,
                      aes(x = Smax_Robinson,
                          y = bathy)) +
  theme_classic() +
  geom_point(aes(colour = Tmean_Robinson),
             size = 1) +
  scale_colour_gradientn(limits = c(-1.1, 8.5),
                        colors=c('red','yellow','green'))+
  ggtitle("Salinity (max Robinson) vs Bathy - coloured by av Temp (R)")

tb_ax1
Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1bathy_v_salMax_temp.png"),
       device = "png",
       dpi=300 )
Salinity v Temp gnmds1
tb_ax1<- ggplot(data = env_sub_meta,
                      aes(x = Smax_Robinson,
                          y = Tmean_Robinson)) +
  theme_classic() +
  geom_point(aes(colour = gnmds1),
             size = 1) +
scale_colour_gradientn(limits = c(-2, 2.5),
                        colors=c('red','yellow','green'))+
  ggtitle("Temp (mean Robinson) vs Salinity (max R) - coloured by gnmds r6 ax 1 - grey 2.5-5")

tb_ax1
Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1tempRmean_v_salinityRmax_nmds1.png"),
       device = "png",
       dpi=300 )
Salinity v Temp dissoxmean
tb_ax1<- ggplot(data = env_sub_meta,
                      aes(x = Smax_Robinson,
                          y = Tmean_Robinson)) +
  theme_classic() +
  geom_point(aes(colour = BO22_dissoxmean_bdmean),
             size = 1) +
scale_colour_gradientn(limits = c(282.5, 372.2),
                        colors=c('red','yellow','green'))+
  ggtitle("Temp (mean Robinson) vs Salinity (max R) - coloured by dissolved oxygen")

tb_ax1
Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1tempRmean_v_salinityRmax_disooxmean.png"),
       device = "png",
       dpi=300 )
TS - icecoverLTMax
tb_ax1<- ggplot(data = env_sub_meta,
                      aes(x = Smax_Robinson,
                          y = Tmean_Robinson)) +
  theme_classic() +
  geom_point(aes(colour = BO22_icecoverltmax_ss),
             size = 1) +
  scale_colour_gradientn(limits = c(0,0.93),
                        colors=c('blue','green','red'))+
  ggtitle("Temp (AvR) v Salinity (maxR) - coloured by ice cover LT max")

tb_ax1
Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1tempRmean_v_salinityRmax_iceCoveLTmax.png"),
       device = "png",
       dpi=800 )
X v Y - temp
tb_ax1<- ggplot(data = env_sub_meta,
                      aes(x = X,
                          y = Y)) +
  theme_classic() +
  geom_point(aes(colour = Tmean_Robinson),
             size = 1) +
  scale_colour_gradientn(limits = c(-1.1, 8.5),
                        colors=c('blue','green','red'))+
  ggtitle("Geography (X v Y) - coloured by mean temp")

ggplotly(tb_ax1)

NA
Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1_X_v_Y_tmeanR.png"),
       device = "png",
       dpi=300 )
Saving 7 x 7 in image
X v Y - density
tb_ax1<- ggplot(data = env_sub_meta,
                      aes(x = X.y,
                          y = Y)) +
  theme_classic() +
  geom_point(aes(colour = swDensRob_avs),
             size = 1) +
  scale_colour_gradientn(limits = c(1027, 1031),
                        colors=c('blue','green','red'))+
  ggtitle("Geography (X v Y) - coloured by water density")

tb_ax1

Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1_X_v_Y_swDenRobavs.png"),
       device = "png",
       dpi=800 )
Saving 7 x 7 in image
X v Y - dissox
tb_ax1<- ggplot(data = env_sub_meta,
                      aes(x = X.y,
                          y = Y)) +
  theme_classic() +
  geom_point(aes(colour = BO22_dissoxmean_bdmean),
             size = 1) +
  scale_colour_gradientn(limits = c(282,373),
                        colors=c('blue','green','red'))+
  ggtitle("Geography (X v Y) - coloured by dissovled oxygen")

tb_ax1

Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1_X_v_Y_dissox.png"),
       device = "png",
       dpi=800 )
X v Y - icecoverLTMax
tb_ax1<- ggplot(data = env_sub_meta,
                      aes(x = X.y,
                          y = Y)) +
  theme_classic() +
  geom_point(aes(colour = BO22_icecoverltmax_ss),
             size = 1) +
  scale_colour_gradientn(limits = c(0.00001,0.93),
                        colors=c('blue','green','red'))+
  ggtitle("Geography (X v Y) - coloured by ice cover LT max - grey <0.00001")

tb_ax1

Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1_X_v_Y_iceCoveLTmax.png"),
       device = "png",
       dpi=800 )
Saving 7 x 7 in image
Temp v disoxltmin gnmds
tb_ax1<- ggplot(data = env_sub_meta,
                      aes(x = Tmean_Robinson,
                          y = BO22_dissoxmean_bdmean)) +
  theme_classic() +
  geom_point(aes(colour = gnmds1),
             size = 1) +
  scale_colour_gradientn(limits = c(-2.3, 2),
                        colors=c('red','yellow','green'))+
  ggtitle("Temp (mean Robinson) v disox mean - coloured by gnmds ax 1")

tb_ax1

Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1_TmeanR_v_dissoxltmin_gnmds1.png"),
       device = "png",
       dpi=300 )
Saving 7 x 7 in image
Temp v disoxltmin bathy
tb_ax1<- ggplot(data = env_sub_meta,
                      aes(x = Tmean_Robinson,
                          y = BO22_dissoxmean_bdmean)) +
  theme_classic() +
  geom_point(aes(colour = bathy),
             size = 1) +
  scale_colour_gradientn(limits = c(-702, -38),
                        colors=c('red','yellow','green'))+
  ggtitle("Temp (mean Robinson) v disox mean - coloured by bathymetry")

tb_ax1

Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1TmeanR_v_dissoxltmin_bathy.png"),
       device = "png",
       dpi=300 )
Saving 7 x 7 in image

Plots with DISCRETE colour scales (variables)

X v Y with mld-bathy categories

dis_split <- ggplot(data = env,
              aes(x = X.y,
                  y = Y)) +
  theme_classic() +
  geom_point(aes(colour = MLDmean_bathy),
             size = 1) +
  scale_colour_manual(values=cbPalette)+
 # scale_colour_brewer(palette = "Set3") +
  ggtitle("Easting vs Northing - coloured by Mixed layer depth proximity")

dis_split

Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1_XvY_MLDmeanBathy.png"),
       device = "png",
       dpi=300 )
Saving 7 x 7 in image

categorise gnmds

env_sub_meta$ax1cat<-cut(env_sub_meta$gnmds1, 
      breaks=c(-3.2,-3,-2,-1,0,1,2,3,3.46))

env_sub_meta$ax2cat<-cut(env_sub_meta$gnmds2, 
      breaks=c(-1.9,-1,0,1,2,3,4,4.9))

X v Y with gnmds ax 1 as HC categories

dis_split <- ggplot(data = env_sub_meta,
              aes(x = X.y,
                  y = Y)) +
  theme_classic() +
  geom_point(aes(colour = ax1cat),
             size = 1) +
 # scale_colour_manual(values=cbPalette) +# non-ordered colourblind pallette
  scale_colour_brewer(palette = "Spectral") + # ordered colourblind pallette
  ggtitle("Easting vs Northing - coloured by gnmds axis 1 HC units")

dis_split

Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1_XvY_ax1cat.png"),
       device = "png",
       dpi=300 )
Saving 7 x 7 in image

categorise temp 5.1

env_sub_meta$temp5_1<-cut(env_sub_meta$Tmean_Robinson, 
      breaks=c(-1.1, 5.1, 8.5))
#

X v Y with temp 5.1

dis_split <- ggplot(data = env_sub_meta,
              aes(x = X.y,
                  y = Y)) +
  theme_classic() +
  geom_point(aes(colour = temp5_1),
             size = 1) +
 # scale_colour_manual(values=cbPalette) +# non-ordered colourblind pallette
  scale_colour_brewer(palette = "Set1") + # ordered colourblind pallette
  ggtitle("Easting vs Northing - coloured by temp thresholded at 5.1*C")

dis_split

Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1_XvY_temp5_1.png"),
       device = "png",
       dpi=300 )
Saving 7 x 7 in image

categorise dissox

env_sub_meta$dissoxav305<-cut(env_sub_meta$BO22_dissoxmean_bdmean, 
     # breaks=c(256, 282, 360)) #ltmin
     breaks=c(282.5,305,372.2),
     labels=c("lowO2","hiO2")) #mean
#

X v Y with dissox

dis_split <- ggplot(data = env_sub_meta,
              aes(x = X.y,
                  y = Y)) +
  theme_classic() +
  geom_point(aes(colour = dissoxav305),
             size = 1) +
 # scale_colour_manual(values=cbPalette) +# non-ordered colourblind pallette
  scale_colour_brewer(palette = "Set1") + # ordered colourblind pallette
  ggtitle("Easting vs Northing - coloured by dissox av thresholded at 305")

dis_split

Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1_XvY_dissoxav305.png"),
       device = "png",
       dpi=300 )
Saving 7 x 7 in image

categorise iceCovLTMax

env_sub_meta$iceMx_gt0<-cut(env_sub_meta$BO22_icecoverltmax_ss, 
      breaks=c(0, 0.00001, 0.92838))
#

X v Y with temp 5.1

dis_split <- ggplot(data = env_sub_meta,
              aes(x = X.y,
                  y = Y)) +
  theme_classic() +
  geom_point(aes(colour = iceMx_gt0),
             size = 1) +
 # scale_colour_manual(values=cbPalette) +# non-ordered colourblind pallette
  scale_colour_brewer(palette = "Set1") + # ordered colourblind pallette
  ggtitle("Easting vs Northing - coloured by ice LT Max thresholded at >0")

dis_split

Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1_XvY_iceLTmx_gt0.png"),
       device = "png",
       dpi=300 )

X v Y with gnmds ax 2 as HC categories

dis_split <- ggplot(data = env_sub_meta,
              aes(x = X.y,
                  y = Y)) +
  theme_classic() +
  geom_point(aes(colour = ax2cat),
             size = 1) +
 # scale_colour_manual(values=cbPalette) +# non-ordered colourblind pallette
  scale_colour_brewer(palette = "Spectral") + # ordered colourblind pallette
  ggtitle("Easting vs Northing - coloured by gnmds axis 2 HC units")

dis_split

Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1_XvY_ax2cat.png"),
       device = "png",
       dpi=300 )
Saving 7 x 7 in image

Gnmds w temp 5.1


t_gmo <- ggplot(data = env_sub_meta,
                     aes(x = gnmds1,
                         y = gnmds2)) +
  theme_classic() +
  coord_fixed() +
  ggtitle("GNMDS coloured by temp 5.1 threshold",
          subtitle = "First run") +
  geom_point(aes(colour = factor(temp5_5))) +
  geom_vline(xintercept = 0,
             linetype = 2,
             colour = "lightgray") +
  geom_hline(yintercept = 0,
             linetype = 2,
             colour = "lightgray")+
  guides(colour=guide_legend(ncol=2))

t_gmo

Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1_gnmds_temp5_1.png"),
       device = "png",
       dpi=300 )
Saving 7 x 7 in image

Gnmds w dissox 305


o_gmo <- ggplot(data = env_sub_meta,
                     aes(x = gnmds1,
                         y = gnmds2)) +
  theme_classic() +
  coord_fixed() +
  ggtitle("GNMDS coloured by dissox 305 threshold",
          subtitle = "First run") +
  geom_point(aes(colour = factor(dissox305))) +
  geom_vline(xintercept = 0,
             linetype = 2,
             colour = "lightgray") +
  geom_hline(yintercept = 0,
             linetype = 2,
             colour = "lightgray")+
  guides(colour=guide_legend(ncol=2))

o_gmo

Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1_gnmds_dissox305.png"),
       device = "png",
       dpi=300 )
Saving 7 x 7 in image

Gnmds w iceLT max >0


i_gmo <- ggplot(data = env_sub_meta,
                     aes(x = gnmds1,
                         y = gnmds2)) +
  theme_classic() +
  coord_fixed() +
  ggtitle("GNMDS coloured by ice max >0 threshold",
          subtitle = "First run") +
  geom_point(aes(colour = factor(iceMx_gt0))) +
  geom_vline(xintercept = 0,
             linetype = 2,
             colour = "lightgray") +
  geom_hline(yintercept = 0,
             linetype = 2,
             colour = "lightgray")+
  guides(colour=guide_legend(ncol=2))

i_gmo

Save the plot
ggsave(filename = file.path(dataPath,"outputs/LoDensNoSB1031p1_gnmds_iceMxgt0.png"),
       device = "png",
       dpi=300 )
comp<-i_gmo+o_gmo+t_gmo
Save the plot


##### Save some outputs

ggexport(comp,
          filename = file.path(dataPath,"outputs/LoDensNoSB1031p1_gnmds_compare.png"),
          width = 1500,
          height = 500)

Save environment

EDIT AREA FIRST!

save.image("I:/Scripts/deepseaNiN/Renv_deepseaNiN_LoDensNoSB1031p1.RData") # edit area first
There were 15 warnings (use warnings() to see them)

NOW CLEAR ENVIRONMENT BEFORE RUNNING FOR NEW AREA

LS0tDQp0aXRsZTogIk1BUkVBTk8gLSBOaU46c3BsaXR0aW5nIGJpb2dlb2dyYXBoaWMgcmVnaW9uc19Mb0RlbnNOb1NCMTAzMXAxIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KQXNzc3VtZXMgeW91IGhhdmUgYXJlYWR5IHJ1bjoNCi0gY29uZmlnDQotIHdvcmtmbG93X2RlZXBzZWFOaU5fU3RhcnQNCg0KWW91IG5vdyBoYXZlIHRoZSBvYmplY3RzIG5lZWRlZCB0byBleHBsb3JlIHRoZSBkYXRhc2V0IGFuZCBmaW5kIHRoZSBiZXN0IHdheSB0byBhcHBseSBiaW9nZW9ncmFwaGljIHNwbGl0cy4gVGhpcyBpcyBhIHByZS1zdGVwIGJlZm9yZSBydW5uaW5nIHRoZSB3b3JrZmxvdyBhZ2FpbiBvbiB0aGUgc3BsaXQgZGF0YXNldCB0byBleHBsb3JlIHBvc3NpYmxlIExLTXMuDQoNCiMgRmluZGluZyBSZWdpb25hbCAoYmlvZ2VvZ3JhcGhpYykgU3BsaXRzDQoNClRoaXMgcmVxdWlyZXMgZXhwbG9yaW5nIHRoZSBkYXRhc2V0IHRvIHRoZW9yaXNlIHRoZSBiZXN0IHdheXMgdG8gc3BsaXQgdGhlIGRhdGEgd2l0aDoNCi0gZW52aXJvbm1lbnRhbCBiaXBsb3RzL2NvbG91cmluZ3MNCg0KDQp0aGVuIGFwcGx5aW5nIHRoZSBzcGxpdHMuIA0KDQoNCiMjIyBMaWJyYXJpZXMNCmBgYHtyfQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KHJlYWR4bCkNCmBgYA0KDQoNCg0KDQojIyBFeHBsb3JpbmcgYmlwbG90cw0KIyMjIyBtYWtlIGZ1bGwgZGF0YXNldCB0byBleHBsb3JlIA0Kc2hvdWxkIGluY2x1ZGUgYWxsIGVudiBWYXJzIGFuZCBvdHVzIHRvIGV4cGxvcmUsIGFuZCBtYWtlIHNwZWNpZXMgcmljaG5lc3MgdmFyaWFibGUNCg0KYGBge3J9DQojYWRkIHNwZWNpZXMgZGF0YSBhbmQgc3AgcmljaG5lc3MgdmFyaWFibGUNCmVudl9zdWJfbWV0YTE8LWNiaW5kKGVudixvdHVfNikNCmVudl9zdWJfbWV0YTEkc3BSaWNoPC1yb3dTdW1zKG90dV82WywtYygxOndoaWNoKGNvbG5hbWVzKG90dV82KT09IlpvYW50aGlkYWUiKSldIT0wKQ0KDQojcmVuYW1lIFgNCmVudl9zdWJfbWV0YTEkWCA8LSBlbnYkWC55DQplbnZfc3ViX21ldGExIDwtZW52X3N1Yl9tZXRhMSAlPiUgc2VsZWN0ICgtYyhYLnkpKQ0KDQojYWRkIHNhbXBsSUQNCmVudl9zdWJfbWV0YTEkU2FtcElEPC1lbnZTZWwkU2FtcElEDQoNCmBgYA0KDQoNCiMjIyBBZGQgcHJvdmlzaW9uYWwgYmlvdG9wZSBkYXRhIHRvIGVudiBmaWxlDQpOb3RlIHRoYXQgYmlvdG9wZXMgd2VyZSBsYXN0IGFzc2lnbmVkIGluIG1hcmNoIDIwMjIgYW5kIHRoZXJlZm9yZSB0aGVyZSBhcmUgc29tZSBhZGRpb25hbCBzYW1wbGVzIHRoYXQgaGF2ZSBub3QgeWV0IGdvdCBhIGJpb3RvcGUgYXNzaWduZWQuIFRoZXNlIHNob3VsZCBqdXN0IGJlIE5Bcw0KYGBge3J9DQpiaW90b3BlSW5mbzwtcmVhZF94bHN4KGZpbGUucGF0aChkYXRhUGF0aCwgImlucHV0cy9NQVJFQU5PX3Byb3Zpc2lvbmFsX2Jpb3RvcGVfY2xhc3NpZmljYXRpb25fMDMyMi54bHN4IiksIHNoZWV0PTEpICU+JQ0KICBzZWxlY3QoLWMoeF9jb29yZGluYXRlX1VUTTMzTiwgeV9jb29yZGluYXRlX1VUTTMzTikpDQoNCmVudl9zdWJfbWV0YTwtbGVmdF9qb2luKGVudl9zdWJfbWV0YTEsYmlvdG9wZUluZm8pDQpgYGANCg0KDQojIyMgYSBjb2xvdXIgcGFsZXR0ZSBmb3IgZGlzY3JldGUgcGxvdHMgKHNlZSBsYXRlciBpbiBzY3JpcHQpDQoNCmBgYHtyfQ0KY2JQYWxldHRlIDwtIGMoIiM5OTk5OTkiLCAiI0U2OUYwMCIsICIjNTZCNEU5IiwgIiMwMDlFNzMiLCAiI0YwRTQ0MiIsICIjMDA3MkIyIiwgIiNENTVFMDAiLCAiI0NDNzlBNyIpDQpgYGANCg0KIyMjIEZpbmQgbWluIG1heCBvZiB2YXJzIGZvciBzY2FsZXMNCmBgYHtyfQ0Kc3VtbWFyeShlbnZfc3ViX21ldGEpDQpgYGANCg0KDQoNCiMjIyBQbG90cyB3aXRoIENPTlRJTlVPVVMgY29sb3VyIHNjYWxlcyAodmFyaWFibGVzKQ0KDQoNCiMjIyMjIEJhdGh5IHYgVGVtcCB3IGdubWRzIGF4IDENCmBgYHtyfQ0KdGJfYXgxPC0gZ2dwbG90KGRhdGEgPSBlbnZfc3ViX21ldGEsDQogICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBUbWVhbl9Sb2JpbnNvbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IGJhdGh5KSkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBnbm1kczEpLA0KICAgICAgICAgICAgIHNpemUgPSAxKSArDQogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4obGltaXRzID0gYygtMi4zLCAxLjkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgY29sb3JzPWMoJ3JlZCcsJ3llbGxvdycsJ2dyZWVuJykpKw0KICBnZ3RpdGxlKCJUZW1wIChtZWFuIFJvYmluc29uKSB2cyBCYXRoeSAtIGNvbG91cmVkIGJ5IGdubWRzIHI2IGF4MSIpDQoNCnRiX2F4MQ0KDQpgYGANCiMjIyMjIFNhdmUgdGhlIHBsb3QNCmBgYHtyfQ0KZ2dzYXZlKGZpbGVuYW1lID0gZmlsZS5wYXRoKGRhdGFQYXRoLCJvdXRwdXRzL0xvRGVuc05vU0IxMDMxcDFiYXRoeV92X3RlbXBfbm1kczEucG5nIiksDQogICAgICAgZGV2aWNlID0gInBuZyIsDQogICAgICAgZHBpPTMwMCApDQpgYGANCiMjIyMjIEJhdGh5IHYgVGVtcCB3IHNhbGluaXR5DQpgYGB7cn0NCnRiX2F4MTwtIGdncGxvdChkYXRhID0gZW52X3N1Yl9tZXRhLA0KICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gVG1lYW5fUm9iaW5zb24sDQogICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBiYXRoeSkpICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gU21heF9Sb2JpbnNvbiksDQogICAgICAgICAgICAgc2l6ZSA9IDEpICsNCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihsaW1pdHMgPSBjKDM0LjQzLCAzNS40MyksDQogICAgICAgICAgICAgICAgICAgICAgICBjb2xvcnM9YygnZ3JlZW4nLCd5ZWxsb3cnLCdibHVlJykpKw0KICBnZ3RpdGxlKCJUZW1wIChtZWFuIFJvYmluc29uKSB2cyBCYXRoeSAtIGNvbG91cmVkIGJ5IHNhbGluaXR5IikNCg0KdGJfYXgxDQoNCmBgYA0KIyMjIyMgU2F2ZSB0aGUgcGxvdA0KYGBge3J9DQpnZ3NhdmUoZmlsZW5hbWUgPSBmaWxlLnBhdGgoZGF0YVBhdGgsIm91dHB1dHMvTG9EZW5zTm9TQjEwMzFwMWJhdGh5X3ZfdGVtcF9zYWxpbml0eU1heC5wbmciKSwNCiAgICAgICBkZXZpY2UgPSAicG5nIiwNCiAgICAgICBkcGk9MzAwICkNCmBgYA0KDQoNCg0KIyMjIyMgQmF0aHkgdiBUZW1wIHcgbG9uZ2l0dWRlDQpgYGB7cn0NCnRiX2F4MTwtIGdncGxvdChkYXRhID0gZW52X3N1Yl9tZXRhLA0KICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gVG1lYW5fUm9iaW5zb24sDQogICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBiYXRoeSkpICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gWC55KSwNCiAgICAgICAgICAgICBzaXplID0gMSkgKw0KICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGxpbWl0cyA9IGMoLTEwNzkzOSwgMTE2MjI2MSksDQogICAgICAgICAgICAgICAgICAgICAgICBjb2xvcnM9YygncmVkJywneWVsbG93JywnYmx1ZScpKSsNCiAgZ2d0aXRsZSgiVGVtcCAobWVhbiBSb2JpbnNvbikgdnMgQmF0aHkgLSBjb2xvdXJlZCBieSBsb25naXR1ZGUiKQ0KDQp0Yl9heDENCg0KYGBgDQojIyMjIyBTYXZlIHRoZSBwbG90DQpgYGB7cn0NCmdnc2F2ZShmaWxlbmFtZSA9IGZpbGUucGF0aChkYXRhUGF0aCwib3V0cHV0cy9Mb0RlbnNOb1NCMTAzMXAxYmF0aHlfdl90ZW1wX2xvbmdpdHVkZS5wbmciKSwNCiAgICAgICBkZXZpY2UgPSAicG5nIiwNCiAgICAgICBkcGk9MzAwICkNCmBgYA0KIyMjIyMgQmF0aHkgdiBUZW1wIHcgbGF0aXR1ZGUNCmBgYHtyfQ0KdGJfYXgxPC0gZ2dwbG90KGRhdGEgPSBlbnZfc3ViX21ldGEsDQogICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBUbWVhbl9Sb2JpbnNvbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IGJhdGh5KSkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBZKSwNCiAgICAgICAgICAgICBzaXplID0gMSkgKw0KICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGxpbWl0cyA9IGMoNjk0NDEzNCwgODk0OTczNCksDQogICAgICAgICAgICAgICAgICAgICAgICBjb2xvcnM9YygncmVkJywneWVsbG93JywnYmx1ZScpKSsNCiAgZ2d0aXRsZSgiVGVtcCAobWVhbiBSb2JpbnNvbikgdnMgQmF0aHkgLSBjb2xvdXJlZCBieSBsYXRpdHVkZSIpDQoNCnRiX2F4MQ0KDQpgYGANCiMjIyMjIFNhdmUgdGhlIHBsb3QNCmBgYHtyfQ0KZ2dzYXZlKGZpbGVuYW1lID0gZmlsZS5wYXRoKGRhdGFQYXRoLCJvdXRwdXRzL0xvRGVuc05vU0IxMDMxcDFiYXRoeV92X3RlbXBfbGF0aXR1ZGUucG5nIiksDQogICAgICAgZGV2aWNlID0gInBuZyIsDQogICAgICAgZHBpPTMwMCApDQpgYGANCiMjIyMjIEJhdGh5IHYgVGVtcCB3IGljZUNvdkxUTWF4DQpgYGB7cn0NCnRiX2F4MTwtIGdncGxvdChkYXRhID0gZW52X3N1Yl9tZXRhLA0KICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gVG1lYW5fUm9iaW5zb24sDQogICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBiYXRoeSkpICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gQk8yMl9pY2Vjb3Zlcmx0bWF4X3NzKSwNCiAgICAgICAgICAgICBzaXplID0gMSkgKw0KICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGxpbWl0cyA9IGMoMCwwLjkzKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9ycz1jKCdncmV5JywndHVycXVvaXNlJywnYmx1ZScpKSsNCiAgZ2d0aXRsZSgiVGVtcCAobWVhbiBSb2JpbnNvbikgdnMgQmF0aHkgLSBjb2xvdXJlZCBieSBpY2UgY292ZXIgTFQgbWF4IikNCg0KdGJfYXgxDQoNCmBgYA0KIyMjIyMgU2F2ZSB0aGUgcGxvdA0KYGBge3J9DQpnZ3NhdmUoZmlsZW5hbWUgPSBmaWxlLnBhdGgoZGF0YVBhdGgsIm91dHB1dHMvTG9EZW5zTm9TQjEwMzFwMWJhdGh5X3ZfdGVtcF9pY2VDb3ZMVG1heC5wbmciKSwNCiAgICAgICBkZXZpY2UgPSAicG5nIiwNCiAgICAgICBkcGk9MzAwICkNCmBgYA0KDQoNCiMjIyMjIEJhdGh5IHYgU2FsaW5pdHkgY29sb3VyZWQgYnkgdGVtcA0KYGBge3J9DQp0Yl9heDE8LSBnZ3Bsb3QoZGF0YSA9IGVudl9zdWJfbWV0YSwNCiAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IFNtYXhfUm9iaW5zb24sDQogICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBiYXRoeSkpICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gVG1lYW5fUm9iaW5zb24pLA0KICAgICAgICAgICAgIHNpemUgPSAxKSArDQogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4obGltaXRzID0gYygtMS4xLCA4LjUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgY29sb3JzPWMoJ3JlZCcsJ3llbGxvdycsJ2dyZWVuJykpKw0KICBnZ3RpdGxlKCJTYWxpbml0eSAobWF4IFJvYmluc29uKSB2cyBCYXRoeSAtIGNvbG91cmVkIGJ5IGF2IFRlbXAgKFIpIikNCg0KdGJfYXgxDQoNCmBgYA0KIyMjIyMgU2F2ZSB0aGUgcGxvdA0KYGBge3J9DQpnZ3NhdmUoZmlsZW5hbWUgPSBmaWxlLnBhdGgoZGF0YVBhdGgsIm91dHB1dHMvTG9EZW5zTm9TQjEwMzFwMWJhdGh5X3Zfc2FsTWF4X3RlbXAucG5nIiksDQogICAgICAgZGV2aWNlID0gInBuZyIsDQogICAgICAgZHBpPTMwMCApDQpgYGANCg0KIyMjIyMgU2FsaW5pdHkgdiBUZW1wIGdubWRzMQ0KYGBge3J9DQp0Yl9heDE8LSBnZ3Bsb3QoZGF0YSA9IGVudl9zdWJfbWV0YSwNCiAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IFNtYXhfUm9iaW5zb24sDQogICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBUbWVhbl9Sb2JpbnNvbikpICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gZ25tZHMxKSwNCiAgICAgICAgICAgICBzaXplID0gMSkgKw0Kc2NhbGVfY29sb3VyX2dyYWRpZW50bihsaW1pdHMgPSBjKC0yLCAyLjUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgY29sb3JzPWMoJ3JlZCcsJ3llbGxvdycsJ2dyZWVuJykpKw0KICBnZ3RpdGxlKCJUZW1wIChtZWFuIFJvYmluc29uKSB2cyBTYWxpbml0eSAobWF4IFIpIC0gY29sb3VyZWQgYnkgZ25tZHMgcjYgYXggMSAtIGdyZXkgMi41LTUiKQ0KDQp0Yl9heDENCg0KYGBgDQojIyMjIyBTYXZlIHRoZSBwbG90DQpgYGB7cn0NCmdnc2F2ZShmaWxlbmFtZSA9IGZpbGUucGF0aChkYXRhUGF0aCwib3V0cHV0cy9Mb0RlbnNOb1NCMTAzMXAxdGVtcFJtZWFuX3Zfc2FsaW5pdHlSbWF4X25tZHMxLnBuZyIpLA0KICAgICAgIGRldmljZSA9ICJwbmciLA0KICAgICAgIGRwaT0zMDAgKQ0KYGBgDQojIyMjIyBTYWxpbml0eSB2IFRlbXAgZGlzc294bWVhbg0KYGBge3J9DQp0Yl9heDE8LSBnZ3Bsb3QoZGF0YSA9IGVudl9zdWJfbWV0YSwNCiAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IFNtYXhfUm9iaW5zb24sDQogICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBUbWVhbl9Sb2JpbnNvbikpICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gQk8yMl9kaXNzb3htZWFuX2JkbWVhbiksDQogICAgICAgICAgICAgc2l6ZSA9IDEpICsNCnNjYWxlX2NvbG91cl9ncmFkaWVudG4obGltaXRzID0gYygyODIuNSwgMzcyLjIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgY29sb3JzPWMoJ3JlZCcsJ3llbGxvdycsJ2dyZWVuJykpKw0KICBnZ3RpdGxlKCJUZW1wIChtZWFuIFJvYmluc29uKSB2cyBTYWxpbml0eSAobWF4IFIpIC0gY29sb3VyZWQgYnkgZGlzc29sdmVkIG94eWdlbiIpDQoNCnRiX2F4MQ0KDQpgYGANCiMjIyMjIFNhdmUgdGhlIHBsb3QNCmBgYHtyfQ0KZ2dzYXZlKGZpbGVuYW1lID0gZmlsZS5wYXRoKGRhdGFQYXRoLCJvdXRwdXRzL0xvRGVuc05vU0IxMDMxcDF0ZW1wUm1lYW5fdl9zYWxpbml0eVJtYXhfZGlzb294bWVhbi5wbmciKSwNCiAgICAgICBkZXZpY2UgPSAicG5nIiwNCiAgICAgICBkcGk9MzAwICkNCmBgYA0KIyMjIyMgVFMgLSBpY2Vjb3ZlckxUTWF4DQpgYGB7cn0NCnRiX2F4MTwtIGdncGxvdChkYXRhID0gZW52X3N1Yl9tZXRhLA0KICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gU21heF9Sb2JpbnNvbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IFRtZWFuX1JvYmluc29uKSkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBCTzIyX2ljZWNvdmVybHRtYXhfc3MpLA0KICAgICAgICAgICAgIHNpemUgPSAxKSArDQogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4obGltaXRzID0gYygwLDAuOTMpLA0KICAgICAgICAgICAgICAgICAgICAgICAgY29sb3JzPWMoJ2JsdWUnLCdncmVlbicsJ3JlZCcpKSsNCiAgZ2d0aXRsZSgiVGVtcCAoQXZSKSB2IFNhbGluaXR5IChtYXhSKSAtIGNvbG91cmVkIGJ5IGljZSBjb3ZlciBMVCBtYXgiKQ0KDQp0Yl9heDENCg0KYGBgDQojIyMjIyBTYXZlIHRoZSBwbG90DQpgYGB7cn0NCmdnc2F2ZShmaWxlbmFtZSA9IGZpbGUucGF0aChkYXRhUGF0aCwib3V0cHV0cy9Mb0RlbnNOb1NCMTAzMXAxdGVtcFJtZWFuX3Zfc2FsaW5pdHlSbWF4X2ljZUNvdmVMVG1heC5wbmciKSwNCiAgICAgICBkZXZpY2UgPSAicG5nIiwNCiAgICAgICBkcGk9ODAwICkNCmBgYA0KDQoNCiMjIyMjIFggdiBZIC0gdGVtcA0KYGBge3J9DQp0Yl9heDE8LSBnZ3Bsb3QoZGF0YSA9IGVudl9zdWJfbWV0YSwNCiAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IFgsDQogICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBZKSkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBUbWVhbl9Sb2JpbnNvbiksDQogICAgICAgICAgICAgc2l6ZSA9IDEpICsNCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihsaW1pdHMgPSBjKC0xLjEsIDguNSksDQogICAgICAgICAgICAgICAgICAgICAgICBjb2xvcnM9YygnYmx1ZScsJ2dyZWVuJywncmVkJykpKw0KICBnZ3RpdGxlKCJHZW9ncmFwaHkgKFggdiBZKSAtIGNvbG91cmVkIGJ5IG1lYW4gdGVtcCIpDQoNCmdncGxvdGx5KHRiX2F4MSkNCg0KYGBgDQojIyMjIyBTYXZlIHRoZSBwbG90DQpgYGB7cn0NCmdnc2F2ZShmaWxlbmFtZSA9IGZpbGUucGF0aChkYXRhUGF0aCwib3V0cHV0cy9Mb0RlbnNOb1NCMTAzMXAxX1hfdl9ZX3RtZWFuUi5wbmciKSwNCiAgICAgICBkZXZpY2UgPSAicG5nIiwNCiAgICAgICBkcGk9MzAwICkNCmBgYA0KDQojIyMjIyBYIHYgWSAtIGRlbnNpdHkNCmBgYHtyfQ0KdGJfYXgxPC0gZ2dwbG90KGRhdGEgPSBlbnZfc3ViX21ldGEsDQogICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBYLnksDQogICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBZKSkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBzd0RlbnNSb2JfYXZzKSwNCiAgICAgICAgICAgICBzaXplID0gMSkgKw0KICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGxpbWl0cyA9IGMoMTAyNywgMTAzMSksDQogICAgICAgICAgICAgICAgICAgICAgICBjb2xvcnM9YygnYmx1ZScsJ2dyZWVuJywncmVkJykpKw0KICBnZ3RpdGxlKCJHZW9ncmFwaHkgKFggdiBZKSAtIGNvbG91cmVkIGJ5IHdhdGVyIGRlbnNpdHkiKQ0KDQp0Yl9heDENCg0KYGBgDQojIyMjIyBTYXZlIHRoZSBwbG90DQpgYGB7cn0NCmdnc2F2ZShmaWxlbmFtZSA9IGZpbGUucGF0aChkYXRhUGF0aCwib3V0cHV0cy9Mb0RlbnNOb1NCMTAzMXAxX1hfdl9ZX3N3RGVuUm9iYXZzLnBuZyIpLA0KICAgICAgIGRldmljZSA9ICJwbmciLA0KICAgICAgIGRwaT04MDAgKQ0KYGBgDQojIyMjIyBYIHYgWSAtIGRpc3NveA0KYGBge3J9DQp0Yl9heDE8LSBnZ3Bsb3QoZGF0YSA9IGVudl9zdWJfbWV0YSwNCiAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IFgueSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IFkpKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IEJPMjJfZGlzc294bWVhbl9iZG1lYW4pLA0KICAgICAgICAgICAgIHNpemUgPSAxKSArDQogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4obGltaXRzID0gYygyODIsMzczKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9ycz1jKCdibHVlJywnZ3JlZW4nLCdyZWQnKSkrDQogIGdndGl0bGUoIkdlb2dyYXBoeSAoWCB2IFkpIC0gY29sb3VyZWQgYnkgZGlzc292bGVkIG94eWdlbiIpDQoNCnRiX2F4MQ0KDQpgYGANCiMjIyMjIFNhdmUgdGhlIHBsb3QNCmBgYHtyfQ0KZ2dzYXZlKGZpbGVuYW1lID0gZmlsZS5wYXRoKGRhdGFQYXRoLCJvdXRwdXRzL0xvRGVuc05vU0IxMDMxcDFfWF92X1lfZGlzc294LnBuZyIpLA0KICAgICAgIGRldmljZSA9ICJwbmciLA0KICAgICAgIGRwaT04MDAgKQ0KYGBgDQojIyMjIyBYIHYgWSAtIGljZWNvdmVyTFRNYXgNCmBgYHtyfQ0KdGJfYXgxPC0gZ2dwbG90KGRhdGEgPSBlbnZfc3ViX21ldGEsDQogICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBYLnksDQogICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBZKSkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBCTzIyX2ljZWNvdmVybHRtYXhfc3MpLA0KICAgICAgICAgICAgIHNpemUgPSAxKSArDQogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4obGltaXRzID0gYygwLjAwMDAxLDAuOTMpLA0KICAgICAgICAgICAgICAgICAgICAgICAgY29sb3JzPWMoJ2JsdWUnLCdncmVlbicsJ3JlZCcpKSsNCiAgZ2d0aXRsZSgiR2VvZ3JhcGh5IChYIHYgWSkgLSBjb2xvdXJlZCBieSBpY2UgY292ZXIgTFQgbWF4IC0gZ3JleSA8MC4wMDAwMSIpDQoNCnRiX2F4MQ0KDQpgYGANCiMjIyMjIFNhdmUgdGhlIHBsb3QNCmBgYHtyfQ0KZ2dzYXZlKGZpbGVuYW1lID0gZmlsZS5wYXRoKGRhdGFQYXRoLCJvdXRwdXRzL0xvRGVuc05vU0IxMDMxcDFfWF92X1lfaWNlQ292ZUxUbWF4LnBuZyIpLA0KICAgICAgIGRldmljZSA9ICJwbmciLA0KICAgICAgIGRwaT04MDAgKQ0KYGBgDQoNCg0KIyMjIyMgVGVtcCB2IGRpc294bHRtaW4gZ25tZHMNCmBgYHtyfQ0KdGJfYXgxPC0gZ2dwbG90KGRhdGEgPSBlbnZfc3ViX21ldGEsDQogICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBUbWVhbl9Sb2JpbnNvbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IEJPMjJfZGlzc294bWVhbl9iZG1lYW4pKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IGdubWRzMSksDQogICAgICAgICAgICAgc2l6ZSA9IDEpICsNCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihsaW1pdHMgPSBjKC0yLjMsIDIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgY29sb3JzPWMoJ3JlZCcsJ3llbGxvdycsJ2dyZWVuJykpKw0KICBnZ3RpdGxlKCJUZW1wIChtZWFuIFJvYmluc29uKSB2IGRpc294IG1lYW4gLSBjb2xvdXJlZCBieSBnbm1kcyBheCAxIikNCg0KdGJfYXgxDQoNCmBgYA0KDQojIyMjIyBTYXZlIHRoZSBwbG90DQpgYGB7cn0NCmdnc2F2ZShmaWxlbmFtZSA9IGZpbGUucGF0aChkYXRhUGF0aCwib3V0cHV0cy9Mb0RlbnNOb1NCMTAzMXAxX1RtZWFuUl92X2Rpc3NveGx0bWluX2dubWRzMS5wbmciKSwNCiAgICAgICBkZXZpY2UgPSAicG5nIiwNCiAgICAgICBkcGk9MzAwICkNCg0KYGBgDQojIyMjIyBUZW1wIHYgZGlzb3hsdG1pbiBiYXRoeQ0KYGBge3J9DQp0Yl9heDE8LSBnZ3Bsb3QoZGF0YSA9IGVudl9zdWJfbWV0YSwNCiAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IFRtZWFuX1JvYmluc29uLA0KICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gQk8yMl9kaXNzb3htZWFuX2JkbWVhbikpICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gYmF0aHkpLA0KICAgICAgICAgICAgIHNpemUgPSAxKSArDQogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4obGltaXRzID0gYygtNzAyLCAtMzgpLA0KICAgICAgICAgICAgICAgICAgICAgICAgY29sb3JzPWMoJ3JlZCcsJ3llbGxvdycsJ2dyZWVuJykpKw0KICBnZ3RpdGxlKCJUZW1wIChtZWFuIFJvYmluc29uKSB2IGRpc294IG1lYW4gLSBjb2xvdXJlZCBieSBiYXRoeW1ldHJ5IikNCg0KdGJfYXgxDQoNCmBgYA0KDQojIyMjIyBTYXZlIHRoZSBwbG90DQpgYGB7cn0NCmdnc2F2ZShmaWxlbmFtZSA9IGZpbGUucGF0aChkYXRhUGF0aCwib3V0cHV0cy9Mb0RlbnNOb1NCMTAzMXAxVG1lYW5SX3ZfZGlzc294bHRtaW5fYmF0aHkucG5nIiksDQogICAgICAgZGV2aWNlID0gInBuZyIsDQogICAgICAgZHBpPTMwMCApDQoNCmBgYA0KDQoNCg0KIyMjIFBsb3RzIHdpdGggRElTQ1JFVEUgY29sb3VyIHNjYWxlcyAodmFyaWFibGVzKQ0KDQojIyMjIFggdiBZIHdpdGggbWxkLWJhdGh5IGNhdGVnb3JpZXMNCmBgYHtyfQ0KZGlzX3NwbGl0IDwtIGdncGxvdChkYXRhID0gZW52LA0KICAgICAgICAgICAgICBhZXMoeCA9IFgueSwNCiAgICAgICAgICAgICAgICAgIHkgPSBZKSkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBNTERtZWFuX2JhdGh5KSwNCiAgICAgICAgICAgICBzaXplID0gMSkgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcz1jYlBhbGV0dGUpKw0KICMgc2NhbGVfY29sb3VyX2JyZXdlcihwYWxldHRlID0gIlNldDMiKSArDQogIGdndGl0bGUoIkVhc3RpbmcgdnMgTm9ydGhpbmcgLSBjb2xvdXJlZCBieSBNaXhlZCBsYXllciBkZXB0aCBwcm94aW1pdHkiKQ0KDQpkaXNfc3BsaXQNCg0KYGBgDQoNCiMjIyMjIFNhdmUgdGhlIHBsb3QNCmBgYHtyfQ0KZ2dzYXZlKGZpbGVuYW1lID0gZmlsZS5wYXRoKGRhdGFQYXRoLCJvdXRwdXRzL0xvRGVuc05vU0IxMDMxcDFfWHZZX01MRG1lYW5CYXRoeS5wbmciKSwNCiAgICAgICBkZXZpY2UgPSAicG5nIiwNCiAgICAgICBkcGk9MzAwICkNCg0KYGBgDQoNCiMjIyBjYXRlZ29yaXNlIGdubWRzDQoNCmBgYHtyfQ0KZW52X3N1Yl9tZXRhJGF4MWNhdDwtY3V0KGVudl9zdWJfbWV0YSRnbm1kczEsIA0KICAgICAgYnJlYWtzPWMoLTMuMiwtMywtMiwtMSwwLDEsMiwzLDMuNDYpKQ0KDQplbnZfc3ViX21ldGEkYXgyY2F0PC1jdXQoZW52X3N1Yl9tZXRhJGdubWRzMiwgDQogICAgICBicmVha3M9YygtMS45LC0xLDAsMSwyLDMsNCw0LjkpKQ0KYGBgDQoNCg0KIyMjIyBYIHYgWSB3aXRoIGdubWRzIGF4IDEgYXMgSEMgY2F0ZWdvcmllcw0KYGBge3J9DQpkaXNfc3BsaXQgPC0gZ2dwbG90KGRhdGEgPSBlbnZfc3ViX21ldGEsDQogICAgICAgICAgICAgIGFlcyh4ID0gWC55LA0KICAgICAgICAgICAgICAgICAgeSA9IFkpKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IGF4MWNhdCksDQogICAgICAgICAgICAgc2l6ZSA9IDEpICsNCiAjIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzPWNiUGFsZXR0ZSkgKyMgbm9uLW9yZGVyZWQgY29sb3VyYmxpbmQgcGFsbGV0dGUNCiAgc2NhbGVfY29sb3VyX2JyZXdlcihwYWxldHRlID0gIlNwZWN0cmFsIikgKyAjIG9yZGVyZWQgY29sb3VyYmxpbmQgcGFsbGV0dGUNCiAgZ2d0aXRsZSgiRWFzdGluZyB2cyBOb3J0aGluZyAtIGNvbG91cmVkIGJ5IGdubWRzIGF4aXMgMSBIQyB1bml0cyIpDQoNCmRpc19zcGxpdA0KDQpgYGANCg0KIyMjIyMgU2F2ZSB0aGUgcGxvdA0KYGBge3J9DQpnZ3NhdmUoZmlsZW5hbWUgPSBmaWxlLnBhdGgoZGF0YVBhdGgsIm91dHB1dHMvTG9EZW5zTm9TQjEwMzFwMV9YdllfYXgxY2F0LnBuZyIpLA0KICAgICAgIGRldmljZSA9ICJwbmciLA0KICAgICAgIGRwaT0zMDAgKQ0KDQpgYGANCg0KIyMjIGNhdGVnb3Jpc2UgdGVtcCA1LjENCg0KYGBge3J9DQplbnZfc3ViX21ldGEkdGVtcDVfMTwtY3V0KGVudl9zdWJfbWV0YSRUbWVhbl9Sb2JpbnNvbiwgDQogICAgICBicmVha3M9YygtMS4xLCA1LjEsIDguNSkpDQojDQpgYGANCg0KDQojIyMjIFggdiBZIHdpdGggdGVtcCA1LjENCmBgYHtyfQ0KZGlzX3NwbGl0IDwtIGdncGxvdChkYXRhID0gZW52X3N1Yl9tZXRhLA0KICAgICAgICAgICAgICBhZXMoeCA9IFgueSwNCiAgICAgICAgICAgICAgICAgIHkgPSBZKSkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSB0ZW1wNV8xKSwNCiAgICAgICAgICAgICBzaXplID0gMSkgKw0KICMgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXM9Y2JQYWxldHRlKSArIyBub24tb3JkZXJlZCBjb2xvdXJibGluZCBwYWxsZXR0ZQ0KICBzY2FsZV9jb2xvdXJfYnJld2VyKHBhbGV0dGUgPSAiU2V0MSIpICsgIyBvcmRlcmVkIGNvbG91cmJsaW5kIHBhbGxldHRlDQogIGdndGl0bGUoIkVhc3RpbmcgdnMgTm9ydGhpbmcgLSBjb2xvdXJlZCBieSB0ZW1wIHRocmVzaG9sZGVkIGF0IDUuMSpDIikNCg0KZGlzX3NwbGl0DQoNCmBgYA0KDQojIyMjIyBTYXZlIHRoZSBwbG90DQpgYGB7cn0NCmdnc2F2ZShmaWxlbmFtZSA9IGZpbGUucGF0aChkYXRhUGF0aCwib3V0cHV0cy9Mb0RlbnNOb1NCMTAzMXAxX1h2WV90ZW1wNV8xLnBuZyIpLA0KICAgICAgIGRldmljZSA9ICJwbmciLA0KICAgICAgIGRwaT0zMDAgKQ0KDQpgYGANCiMjIyBjYXRlZ29yaXNlIGRpc3NveA0KDQpgYGB7cn0NCmVudl9zdWJfbWV0YSRkaXNzb3hhdjMwNTwtY3V0KGVudl9zdWJfbWV0YSRCTzIyX2Rpc3NveG1lYW5fYmRtZWFuLCANCiAgICAgIyBicmVha3M9YygyNTYsIDI4MiwgMzYwKSkgI2x0bWluDQogICAgIGJyZWFrcz1jKDI4Mi41LDMwNSwzNzIuMiksDQogICAgIGxhYmVscz1jKCJsb3dPMiIsImhpTzIiKSkgI21lYW4NCiMNCmBgYA0KDQoNCiMjIyMgWCB2IFkgd2l0aCBkaXNzb3gNCmBgYHtyfQ0KZGlzX3NwbGl0IDwtIGdncGxvdChkYXRhID0gZW52X3N1Yl9tZXRhLA0KICAgICAgICAgICAgICBhZXMoeCA9IFgueSwNCiAgICAgICAgICAgICAgICAgIHkgPSBZKSkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBkaXNzb3hhdjMwNSksDQogICAgICAgICAgICAgc2l6ZSA9IDEpICsNCiAjIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzPWNiUGFsZXR0ZSkgKyMgbm9uLW9yZGVyZWQgY29sb3VyYmxpbmQgcGFsbGV0dGUNCiAgc2NhbGVfY29sb3VyX2JyZXdlcihwYWxldHRlID0gIlNldDEiKSArICMgb3JkZXJlZCBjb2xvdXJibGluZCBwYWxsZXR0ZQ0KICBnZ3RpdGxlKCJFYXN0aW5nIHZzIE5vcnRoaW5nIC0gY29sb3VyZWQgYnkgZGlzc294IGF2IHRocmVzaG9sZGVkIGF0IDMwNSIpDQoNCmRpc19zcGxpdA0KDQpgYGANCg0KIyMjIyMgU2F2ZSB0aGUgcGxvdA0KYGBge3J9DQpnZ3NhdmUoZmlsZW5hbWUgPSBmaWxlLnBhdGgoZGF0YVBhdGgsIm91dHB1dHMvTG9EZW5zTm9TQjEwMzFwMV9YdllfZGlzc294YXYzMDUucG5nIiksDQogICAgICAgZGV2aWNlID0gInBuZyIsDQogICAgICAgZHBpPTMwMCApDQoNCmBgYA0KDQojIyMgY2F0ZWdvcmlzZSBpY2VDb3ZMVE1heA0KDQpgYGB7cn0NCmVudl9zdWJfbWV0YSRpY2VNeF9ndDA8LWN1dChlbnZfc3ViX21ldGEkQk8yMl9pY2Vjb3Zlcmx0bWF4X3NzLCANCiAgICAgIGJyZWFrcz1jKDAsIDAuMDAwMDEsIDAuOTI4MzgpKQ0KIw0KYGBgDQoNCg0KIyMjIyBYIHYgWSB3aXRoIHRlbXAgNS4xDQpgYGB7cn0NCmRpc19zcGxpdCA8LSBnZ3Bsb3QoZGF0YSA9IGVudl9zdWJfbWV0YSwNCiAgICAgICAgICAgICAgYWVzKHggPSBYLnksDQogICAgICAgICAgICAgICAgICB5ID0gWSkpICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gaWNlTXhfZ3QwKSwNCiAgICAgICAgICAgICBzaXplID0gMSkgKw0KICMgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXM9Y2JQYWxldHRlKSArIyBub24tb3JkZXJlZCBjb2xvdXJibGluZCBwYWxsZXR0ZQ0KICBzY2FsZV9jb2xvdXJfYnJld2VyKHBhbGV0dGUgPSAiU2V0MSIpICsgIyBvcmRlcmVkIGNvbG91cmJsaW5kIHBhbGxldHRlDQogIGdndGl0bGUoIkVhc3RpbmcgdnMgTm9ydGhpbmcgLSBjb2xvdXJlZCBieSBpY2UgTFQgTWF4IHRocmVzaG9sZGVkIGF0ID4wIikNCg0KZGlzX3NwbGl0DQoNCmBgYA0KDQojIyMjIyBTYXZlIHRoZSBwbG90DQpgYGB7cn0NCmdnc2F2ZShmaWxlbmFtZSA9IGZpbGUucGF0aChkYXRhUGF0aCwib3V0cHV0cy9Mb0RlbnNOb1NCMTAzMXAxX1h2WV9pY2VMVG14X2d0MC5wbmciKSwNCiAgICAgICBkZXZpY2UgPSAicG5nIiwNCiAgICAgICBkcGk9MzAwICkNCg0KYGBgDQoNCg0KDQoNCiMjIyMgWCB2IFkgd2l0aCBnbm1kcyBheCAyIGFzIEhDIGNhdGVnb3JpZXMNCmBgYHtyfQ0KZGlzX3NwbGl0IDwtIGdncGxvdChkYXRhID0gZW52X3N1Yl9tZXRhLA0KICAgICAgICAgICAgICBhZXMoeCA9IFgueSwNCiAgICAgICAgICAgICAgICAgIHkgPSBZKSkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBheDJjYXQpLA0KICAgICAgICAgICAgIHNpemUgPSAxKSArDQogIyBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcz1jYlBhbGV0dGUpICsjIG5vbi1vcmRlcmVkIGNvbG91cmJsaW5kIHBhbGxldHRlDQogIHNjYWxlX2NvbG91cl9icmV3ZXIocGFsZXR0ZSA9ICJTcGVjdHJhbCIpICsgIyBvcmRlcmVkIGNvbG91cmJsaW5kIHBhbGxldHRlDQogIGdndGl0bGUoIkVhc3RpbmcgdnMgTm9ydGhpbmcgLSBjb2xvdXJlZCBieSBnbm1kcyBheGlzIDIgSEMgdW5pdHMiKQ0KDQpkaXNfc3BsaXQNCg0KYGBgDQoNCg0KDQoNCiMjIyMjIFNhdmUgdGhlIHBsb3QNCmBgYHtyfQ0KZ2dzYXZlKGZpbGVuYW1lID0gZmlsZS5wYXRoKGRhdGFQYXRoLCJvdXRwdXRzL0xvRGVuc05vU0IxMDMxcDFfWHZZX2F4MmNhdC5wbmciKSwNCiAgICAgICBkZXZpY2UgPSAicG5nIiwNCiAgICAgICBkcGk9MzAwICkNCg0KYGBgDQoNCiMjIyMgR25tZHMgdyB0ZW1wIDUuMQ0KYGBge3J9DQoNCnRfZ21vIDwtIGdncGxvdChkYXRhID0gZW52X3N1Yl9tZXRhLA0KICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBnbm1kczEsDQogICAgICAgICAgICAgICAgICAgICAgICAgeSA9IGdubWRzMikpICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgY29vcmRfZml4ZWQoKSArDQogIGdndGl0bGUoIkdOTURTIGNvbG91cmVkIGJ5IHRlbXAgNS4xIHRocmVzaG9sZCIsDQogICAgICAgICAgc3VidGl0bGUgPSAiRmlyc3QgcnVuIikgKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBmYWN0b3IodGVtcDVfNSkpKSArDQogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsDQogICAgICAgICAgICAgbGluZXR5cGUgPSAyLA0KICAgICAgICAgICAgIGNvbG91ciA9ICJsaWdodGdyYXkiKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsDQogICAgICAgICAgICAgbGluZXR5cGUgPSAyLA0KICAgICAgICAgICAgIGNvbG91ciA9ICJsaWdodGdyYXkiKSsNCiAgZ3VpZGVzKGNvbG91cj1ndWlkZV9sZWdlbmQobmNvbD0yKSkNCg0KdF9nbW8NCmBgYA0KIyMjIyMgU2F2ZSB0aGUgcGxvdA0KYGBge3J9DQpnZ3NhdmUoZmlsZW5hbWUgPSBmaWxlLnBhdGgoZGF0YVBhdGgsIm91dHB1dHMvTG9EZW5zTm9TQjEwMzFwMV9nbm1kc190ZW1wNV8xLnBuZyIpLA0KICAgICAgIGRldmljZSA9ICJwbmciLA0KICAgICAgIGRwaT0zMDAgKQ0KYGBgDQojIyMjIEdubWRzIHcgZGlzc294IDMwNQ0KYGBge3J9DQoNCm9fZ21vIDwtIGdncGxvdChkYXRhID0gZW52X3N1Yl9tZXRhLA0KICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBnbm1kczEsDQogICAgICAgICAgICAgICAgICAgICAgICAgeSA9IGdubWRzMikpICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgY29vcmRfZml4ZWQoKSArDQogIGdndGl0bGUoIkdOTURTIGNvbG91cmVkIGJ5IGRpc3NveCAzMDUgdGhyZXNob2xkIiwNCiAgICAgICAgICBzdWJ0aXRsZSA9ICJGaXJzdCBydW4iKSArDQogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IGZhY3RvcihkaXNzb3gzMDUpKSkgKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLA0KICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwNCiAgICAgICAgICAgICBjb2xvdXIgPSAibGlnaHRncmF5IikgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLA0KICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwNCiAgICAgICAgICAgICBjb2xvdXIgPSAibGlnaHRncmF5IikrDQogIGd1aWRlcyhjb2xvdXI9Z3VpZGVfbGVnZW5kKG5jb2w9MikpDQoNCm9fZ21vDQpgYGANCiMjIyMjIFNhdmUgdGhlIHBsb3QNCmBgYHtyfQ0KZ2dzYXZlKGZpbGVuYW1lID0gZmlsZS5wYXRoKGRhdGFQYXRoLCJvdXRwdXRzL0xvRGVuc05vU0IxMDMxcDFfZ25tZHNfZGlzc294MzA1LnBuZyIpLA0KICAgICAgIGRldmljZSA9ICJwbmciLA0KICAgICAgIGRwaT0zMDAgKQ0KYGBgDQoNCiMjIyMgR25tZHMgdyBpY2VMVCBtYXggPjANCmBgYHtyfQ0KDQppX2dtbyA8LSBnZ3Bsb3QoZGF0YSA9IGVudl9zdWJfbWV0YSwNCiAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gZ25tZHMxLA0KICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBnbm1kczIpKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIGNvb3JkX2ZpeGVkKCkgKw0KICBnZ3RpdGxlKCJHTk1EUyBjb2xvdXJlZCBieSBpY2UgbWF4ID4wIHRocmVzaG9sZCIsDQogICAgICAgICAgc3VidGl0bGUgPSAiRmlyc3QgcnVuIikgKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBmYWN0b3IoaWNlTXhfZ3QwKSkpICsNCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwNCiAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsDQogICAgICAgICAgICAgY29sb3VyID0gImxpZ2h0Z3JheSIpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwNCiAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsDQogICAgICAgICAgICAgY29sb3VyID0gImxpZ2h0Z3JheSIpKw0KICBndWlkZXMoY29sb3VyPWd1aWRlX2xlZ2VuZChuY29sPTIpKQ0KDQppX2dtbw0KYGBgDQojIyMjIyBTYXZlIHRoZSBwbG90DQpgYGB7cn0NCmdnc2F2ZShmaWxlbmFtZSA9IGZpbGUucGF0aChkYXRhUGF0aCwib3V0cHV0cy9Mb0RlbnNOb1NCMTAzMXAxX2dubWRzX2ljZU14Z3QwLnBuZyIpLA0KICAgICAgIGRldmljZSA9ICJwbmciLA0KICAgICAgIGRwaT0zMDAgKQ0KYGBgDQoNCmBgYHtyfQ0KY29tcDwtaV9nbW8rb19nbW8rdF9nbW8NCmBgYA0KIyMjIyMgU2F2ZSB0aGUgcGxvdA0KYGBge3J9DQoNCg0KIyMjIyMgU2F2ZSBzb21lIG91dHB1dHMNCg0KZ2dleHBvcnQoY29tcCwNCiAgICAgICAgICBmaWxlbmFtZSA9IGZpbGUucGF0aChkYXRhUGF0aCwib3V0cHV0cy9Mb0RlbnNOb1NCMTAzMXAxX2dubWRzX2NvbXBhcmUucG5nIiksDQogICAgICAgICAgd2lkdGggPSAxNTAwLA0KICAgICAgICAgIGhlaWdodCA9IDUwMCkNCg0KYGBgDQoNCg0KDQojIFNhdmUgZW52aXJvbm1lbnQNCg0KRURJVCBBUkVBIEZJUlNUIQ0KDQpgYGB7cn0NCnNhdmUuaW1hZ2UoIkk6L1NjcmlwdHMvZGVlcHNlYU5pTi9SZW52X2RlZXBzZWFOaU5fTG9EZW5zTm9TQjEwMzFwMS5SRGF0YSIpICMgZWRpdCBhcmVhIGZpcnN0DQoNCmBgYA0KDQpOT1cgQ0xFQVIgRU5WSVJPTk1FTlQgQkVGT1JFIFJVTk5JTkcgRk9SIE5FVyBBUkVBDQoNCg==